//Source file: D:\\WTK104\\apps\\Toddtris\\src\\com\\toddsoft\\toddtris\\midlet\\ToddtrisMIDlet.java

package com.toddsoft.toddtris.model;

import com.toddsoft.util.ByteArrayHandler;
import com.toddsoft.toddtris.model.Well;
import com.toddsoft.toddtris.model.WellListener;

/**
 * Class which implements a high score table which contains one high score for
 * each of the possible height and level combinations for a particular
 * game type
 * e.g. one HighScoreTable for all marathon high scores, another for all
 * twenty five line high scores and a third for all forty line high scores
 */
public class HighScoreTable implements WellListener {

    private int[][] highScores;
    private int maxHeight;

    /* the steps in which starting heights are available */
    private int heightMultiplier; 
    private int maxLevel;

    /* the steps in which starting levels are available */
    private int levelMultiplier;

    private int listenTargetLines;


    public HighScoreTable(Well well,
                          int maxHeight,
                          int heightMultiplier,
                          int maxLevel,
                          int levelMultiplier,
                          int listenTargetLines) {

        this.maxHeight = maxHeight;
        this.heightMultiplier = heightMultiplier;
        this.maxLevel = maxLevel;
        this.levelMultiplier = levelMultiplier;
        this.listenTargetLines = listenTargetLines;
        highScores = new int[maxHeight + 1][maxLevel + 1];
        well.addListener(this);
    }

    public HighScoreTable(Well well,
                          int maxHeight,
                          int heightMultiplier,
                          int maxLevel,
                          int levelMultiplier,
                          int listenTargetLines,
                          byte[] bytes) {
        this(well, 
             maxHeight,
             heightMultiplier,
             maxLevel,
             levelMultiplier,
             listenTargetLines);

        ByteArrayHandler bah = new ByteArrayHandler(bytes);

        /* get the high scores */
        for (int i = 0; i <= maxHeight; i++) {
            for (int j = 0; j <= maxLevel; j++) {
                highScores[i][j] = bah.getInt();
            }
        }
    }
                
    public static int getCurrentHighScore(Well well,
                                          HighScoreTable[] hsta) {
        if (hsta == null) {
            return 0;
        }

        for (int i = 0; i < hsta.length; i++) {
            int hs = hsta[i].getCurrentHighScore(well);
            if (hs > 0) {
                return hs;
            }
        }
        return 0;
    }

    public static void updateHighScores(Well well,
                                        HighScoreTable[] hsta) {
        if (hsta == null) {
            return;
        }
        
        for (int i = 0; i < hsta.length; i++) {
            hsta[i].updateHighScores(well);
        }
    }

    /**
     * @return byte[]
     */
    public byte[] toByteArray() {

        ByteArrayHandler bah = new ByteArrayHandler();
        
        /* write the high scores */
        for (int i = 0; i <= this.maxHeight; i++) {
            for (int j = 0; j <= this.maxLevel; j++) {
                bah.addInt(highScores[i][j]);
            }
        }

        return bah.getBytes();     
    }

    public int getCurrentHighScore(Well well) {

        /* if target lines doesn't match return 0 - wrong HST */
        if (this.listenTargetLines != well.getTargetLines()) {
            return 0;
        }

        int heightIndex = (int)(well.getStartHeight() 
                                / this.heightMultiplier);

        if ( heightIndex < 0 || heightIndex > this.maxHeight) {

            /* avoid array index OOB */
            return 0;
        }

        int levelIndex = (int)(well.getLevel() / levelMultiplier);

        if ( levelIndex < 0 || levelIndex > maxLevel) {

            /* avoid array index OOB */
            return 0;
        }

        return highScores[heightIndex][levelIndex];
    }

    /**
     * WellListener Methods
     */

    /*
     * @param well
     */
    public void gameOver(Well well) {
        /* can only get a high score if this was a marathon game */
        if (well.getTargetLines() == 0) {
            this.updateHighScores(well);     
        }
    }

    /**
     * @param well
     */
    public void complete(Well well) {
        this.updateHighScores(well);     
    }
    
    /**
     * @param well
     */
    public void wellChanged(Well well) {
        // do nothing     
    }
    
    /**
     * @param well
     * @param linesMade
     */
    public void madeLines(Well well, int linesMade) {
        // do nothing     
    }
    
    /**
     * @param well
     */
    public void wellReset(Well well) {
        // do nothing     
    }
    
    /**
     * @param well
     */
    public void blockLanded(Well well) {
        // do nothing     
    }
    
    private void updateHighScores(Well well) {

        /* if target lines doesn't match return 0 - wrong HST */
        if (this.listenTargetLines != well.getTargetLines()) {
            return;
        }

        int heightIndex = (int)(well.getStartHeight() 
                                / this.heightMultiplier);

        if ( heightIndex < 0 || heightIndex > this.maxHeight) {

            /* avoid array index OOB */
            return;
        }

        int levelIndex = (int)(well.getLevel() / levelMultiplier);

        if ( levelIndex < 0 || levelIndex > maxLevel) {

            /* avoid array index OOB */
            return;
        }

        if (well.getTargetLines() == 0) {
            /* marathon */
            if (well.getLines() > this.highScores[heightIndex][levelIndex]) {
                this.highScores[heightIndex][levelIndex] = well.getLines();
            }
        } else {
            /* time trial */
            int timeSecs = (int)(well.getRunningTimeInMillis() / 1000);
            int currentHighScore = this.highScores[heightIndex][levelIndex];
            if ( (currentHighScore == 0) || (currentHighScore > timeSecs)) {
                this.highScores[heightIndex][levelIndex] = timeSecs;
            }
        }
    }
}
